package com.ben.multiple.elasticsearch.template;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
import co.elastic.clients.elasticsearch._types.aggregations.StatsAggregate;
import co.elastic.clients.elasticsearch._types.aggregations.StatsAggregation;
import co.elastic.clients.elasticsearch._types.aggregations.StringTermsBucket;
import co.elastic.clients.elasticsearch._types.aggregations.TermsAggregation;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch._types.query_dsl.RangeQuery;
import co.elastic.clients.json.JsonData;
import co.elastic.clients.util.NamedValue;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchAggregation;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchAggregations;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchClients;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class JavaAggTest {
    static ElasticsearchTemplate template;
    static ElasticsearchClient client;
    static String IndexName = "phone";
    static IndexCoordinates indexCoordinates = IndexCoordinates.of(IndexName);

    static {
        client = ElasticsearchClients.createImperative(ClientConfiguration.create("192.168.229.141:9200"));
        template = new ElasticsearchTemplate(client);
    }

    public static void main(String[] args) {
        try {
            metric();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("=========================================");
        client.shutdown();
        System.exit(5);
    }

    static void metric() {
        List<NamedValue<SortOrder>> list = new ArrayList<>();
        NamedValue<SortOrder> orderNamedValue = NamedValue.of("scoreAgg.avg", SortOrder.Asc);
        list.add(orderNamedValue);

        RangeQuery rangeQuery = new RangeQuery.Builder().field("score").gte(JsonData.of(80)).build();

        Aggregation statAgg = new Aggregation.Builder().stats(new StatsAggregation.Builder().field("score").build()).build();
        Aggregation aggregation = new Aggregation.Builder()
                .terms(new TermsAggregation.Builder().field("brand").order(list).build())
                .aggregations("scoreAgg", statAgg)

                .build();
        NativeQuery nativeQuery = NativeQuery.builder().withQuery(new Query(rangeQuery)).withAggregation("brandAgg", aggregation).build();

        SearchHits<HashMap> hits = template.search(nativeQuery, HashMap.class, indexCoordinates);

        ElasticsearchAggregations aggregations = (ElasticsearchAggregations) (hits.getAggregations());
        Map<String, ElasticsearchAggregation> aggregationMap = aggregations.aggregationsAsMap();
        for (Map.Entry<String, ElasticsearchAggregation> entry : aggregationMap.entrySet()) {
            System.out.println(entry.getKey());
            Aggregate aggregate = entry.getValue().aggregation().getAggregate();
            List<StringTermsBucket> bucketList = aggregate.sterms().buckets().array();
            for (StringTermsBucket bucket : bucketList) {
                System.out.println(bucket.key().stringValue() + " : " + bucket.docCount());
                StatsAggregate statsAggregate = bucket.aggregations().get("scoreAgg").stats();
                System.out.println(statsAggregate);
            }
        }
    }

    static void bucket() {
        RangeQuery rangeQuery = new RangeQuery.Builder().field("score").gte(JsonData.of(80)).build();
        Aggregation aggregation = new Aggregation.Builder().terms(new TermsAggregation.Builder().field("brand").build()).build();
        NativeQuery nativeQuery = NativeQuery.builder().withQuery(new Query(rangeQuery)).withAggregation("brandAgg", aggregation).build();

        SearchHits<HashMap> hits = template.search(nativeQuery, HashMap.class, indexCoordinates);

        ElasticsearchAggregations aggregations = (ElasticsearchAggregations) (hits.getAggregations());
        Map<String, ElasticsearchAggregation> aggregationMap = aggregations.aggregationsAsMap();
        for (Map.Entry<String, ElasticsearchAggregation> entry : aggregationMap.entrySet()) {
            System.out.println(entry.getKey());
            Aggregate aggregate = entry.getValue().aggregation().getAggregate();
            List<StringTermsBucket> bucketList = aggregate.sterms().buckets().array();
            for (StringTermsBucket bucket : bucketList) {
                System.out.println(bucket.key().stringValue() + " : " + bucket.docCount());
            }
        }
    }

}
